home *** CD-ROM | disk | FTP | other *** search
/ Maclife 157 / MACLIFE157-2001-09.ISO.7z / MACLIFE157-2001-09.ISO / Linux / MacOS Tools / Other / BootX 1.1.3 (for Old Mac OS) / Sources / lib / From MoreFiles / FSpCompat.c < prev    next >
Text File  |  2001-07-23  |  26KB  |  929 lines

  1. /*
  2. **    Apple Macintosh Developer Technical Support
  3. **
  4. **    FSSpec compatibility functions.
  5. **
  6. **    by Jim Luther, Apple Developer Technical Support Emeritus
  7. **
  8. **    File:        FSpCompat.c
  9. **
  10. **    Copyright ゥ 1992-1998 Apple Computer, Inc.
  11. **    All rights reserved.
  12. **
  13. **    You may incorporate this sample code into your applications without
  14. **    restriction, though the sample code has been provided "AS IS" and the
  15. **    responsibility for its operation is 100% yours.  However, what you are
  16. **    not permitted to do is to redistribute the source as "DSC Sample Code"
  17. **    after having made changes. If you're going to re-distribute the source,
  18. **    we require that you make it clear in the source that the code was
  19. **    descended from Apple Sample Code, but that you've made changes.
  20. */
  21.  
  22. /*
  23. **    If building application 68K code, set GENERATENODATA to 0 for faster code.
  24. **    If building stand-alone 68K code, set GENERATENODATA to 1 so globals
  25. **        (static variables) are not used.
  26. */
  27. #ifndef GENERATENODATA
  28. #define GENERATENODATA 0
  29. #endif
  30.  
  31. #include <Types.h>
  32. #include <Errors.h>
  33. #include <LowMem.h>
  34. #include <Gestalt.h>
  35. #include <Resources.h>
  36. #include <Script.h>
  37.  
  38. #define    __COMPILINGMOREFILES
  39.  
  40. #include "MoreFilesExtras.h"
  41. #include "FSpCompat.h"
  42.  
  43. /*****************************************************************************/
  44.  
  45. /* local constants */
  46.  
  47. enum {
  48.     gestaltBugFixAttrsTwo                    = 'bugy',
  49.     gestaltFSpExchangeFilesCompatibilityFix    = 26,
  50.     gestaltBugFixAttrsThree                    = 'bugx',
  51.     gestaltFSpCreateScriptSupportFix        = 1
  52. };
  53.  
  54. /*****************************************************************************/
  55.  
  56. /* static prototypes */
  57.  
  58.  
  59. #if !__MACOSSEVENORLATER
  60. static    Boolean    FSHasFSSpecCalls(void);
  61.  
  62. static    Boolean    QTHasFSSpecCalls(void);
  63. #endif    /* !__MACOSSEVENORLATER */
  64.  
  65. #if !__MACOSSEVENFIVEORLATER
  66. static    Boolean    HasFSpExchangeFilesCompatibilityFix(void);
  67.  
  68. static    OSErr    GenerateUniqueName(short volume,
  69.                                    long *startSeed,
  70.                                    long dir1,
  71.                                    long dir2,
  72.                                    StringPtr uniqueName);
  73. #endif    /* !__MACOSSEVENFIVEORLATER */
  74.  
  75. #if !__MACOSSEVENFIVEONEORLATER
  76. static    Boolean    HasFSpCreateScriptSupportFix(void);
  77. #endif    /* !__MACOSSEVENFIVEONEORLATER */
  78.  
  79. /*****************************************************************************/
  80.  
  81. /* FSHasFSSpecCalls returns true if the file system provides FSSpec calls. */
  82.  
  83. #if !__MACOSSEVENORLATER
  84. static    Boolean    FSHasFSSpecCalls(void)
  85. {
  86.     long            response;
  87. #if !GENERATENODATA
  88.     static Boolean    tested = false;
  89.     static Boolean    result = false;
  90. #else
  91.     Boolean    result = false;
  92. #endif
  93.     
  94. #if !GENERATENODATA
  95.     if ( !tested )
  96.     {
  97.         tested = true;
  98. #endif
  99.         if ( Gestalt(gestaltFSAttr, &response) == noErr )
  100.         {
  101.             result = ((response & (1L << gestaltHasFSSpecCalls)) != 0);
  102.         }
  103. #if !GENERATENODATA
  104.     }
  105. #endif
  106.     return ( result );
  107. }
  108. #endif    /* !__MACOSSEVENORLATER */
  109.  
  110. /*****************************************************************************/
  111.  
  112. /* QTHasFSSpecCalls returns true if QuickTime provides FSSpec calls */
  113. /* except for FSpExchangeFiles. */
  114.  
  115. #if !__MACOSSEVENORLATER
  116. static    Boolean    QTHasFSSpecCalls(void)
  117. {
  118.     long            response;
  119. #if !GENERATENODATA
  120.     static Boolean    tested = false;
  121.     static Boolean    result = false;
  122. #else
  123.     Boolean    result = false;
  124. #endif
  125.     
  126. #if !GENERATENODATA
  127.     if ( !tested )
  128.     {
  129.         tested = true;
  130. #endif
  131.         result = (Gestalt(gestaltQuickTimeVersion, &response) == noErr);
  132. #if !GENERATENODATA
  133.     }
  134. #endif
  135.     return ( result );
  136. }
  137. #endif    /* !__MACOSSEVENORLATER */
  138.  
  139. /*****************************************************************************/
  140.  
  141. /* HasFSpExchangeFilesCompatibilityFix returns true if FSpExchangeFiles */
  142. /* compatibility code has been fixed in system software. */
  143. /* This was fixed by System Update 3.0, so if SystemSevenFiveOrLater */
  144. /* is true, then we know the fix is in. */
  145.  
  146. #if !__MACOSSEVENFIVEORLATER
  147. static    Boolean    HasFSpExchangeFilesCompatibilityFix(void)
  148. {
  149.     long            response;
  150. #if !GENERATENODATA
  151.     static Boolean    tested = false;
  152.     static Boolean    result = false;
  153. #else    /* !GENERATENODATA */
  154.     Boolean    result = false;
  155. #endif    /* !GENERATENODATA */
  156.     
  157. #if !GENERATENODATA
  158.     if ( !tested )
  159.     {
  160.         tested = true;
  161. #endif    /* !GENERATENODATA */
  162.         if ( Gestalt(gestaltBugFixAttrsTwo, &response) == noErr )
  163.         {
  164.             result = ((response & (1L << gestaltFSpExchangeFilesCompatibilityFix)) != 0);
  165.         }
  166. #if !GENERATENODATA
  167.     }
  168. #endif    /* !GENERATENODATA */
  169.     return ( result );
  170. }
  171. #endif    /* !__MACOSSEVENFIVEORLATER */
  172.  
  173. /*****************************************************************************/
  174.  
  175. /* HasFSpCreateScriptSupportFix returns true if FSpCreate and */
  176. /* FSpCreateResFile have been fixed in system software to correctly set */
  177. /* the scriptCode in the volume's catalog. */
  178. /* This was fixed by System 7.5 Update 1.0 */
  179.  
  180. #if !__MACOSSEVENFIVEONEORLATER
  181. static    Boolean    HasFSpCreateScriptSupportFix(void)
  182. {
  183.     long            response;
  184. #if !GENERATENODATA
  185.     static Boolean    tested = false;
  186.     static Boolean    result = false;
  187. #else
  188.     Boolean    result = false;
  189. #endif    /* !GENERATENODATA */
  190.     
  191. #if !GENERATENODATA
  192.     if ( !tested )
  193.     {
  194.         tested = true;
  195. #endif    /* !GENERATENODATA */
  196.         if ( Gestalt(gestaltBugFixAttrsThree, &response) == noErr )
  197.         {
  198.             result = ((response & (1L << gestaltFSpCreateScriptSupportFix)) != 0);
  199.         }
  200. #if !GENERATENODATA
  201.     }
  202. #endif    /* !GENERATENODATA */
  203.     return ( result );
  204. }
  205. #endif    /* !__MACOSSEVENFIVEONEORLATER */
  206.  
  207. /*****************************************************************************/
  208.  
  209. /*
  210. **    File Manager FSp calls
  211. */
  212.  
  213. /*****************************************************************************/
  214.  
  215. pascal    OSErr    FSMakeFSSpecCompat(short vRefNum,
  216.                                    long dirID,
  217.                                    ConstStr255Param fileName,
  218.                                    FSSpec *spec)
  219. {
  220.     OSErr    result;
  221.     
  222. #if !__MACOSSEVENORLATER
  223.     if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
  224.     {
  225.         Boolean    isDirectory;
  226.         
  227.         result = GetObjectLocation(vRefNum, dirID, fileName,
  228.                                     &(spec->vRefNum), &(spec->parID), spec->name,
  229.                                     &isDirectory);
  230.     }
  231.     else
  232. #endif    /* !__MACOSSEVENORLATER */
  233.     {
  234.         /* Let the file system create the FSSpec if it can since it does the job */
  235.         /* much more efficiently than I can. */
  236.         result = FSMakeFSSpec(vRefNum, dirID, fileName, spec);
  237.  
  238.         /* Fix a bug in Macintosh PC Exchange's MakeFSSpec code where 0 is */
  239.         /* returned in the parID field when making an FSSpec to the volume's */
  240.         /* root directory by passing a full pathname in MakeFSSpec's */
  241.         /* fileName parameter. Fixed in Mac OS 8.1 */
  242.         if ( (result == noErr) && (spec->parID == 0) )
  243.             spec->parID = fsRtParID;
  244.     }
  245.     return ( result );
  246. }
  247.  
  248. /*****************************************************************************/
  249.  
  250. pascal    OSErr    FSpOpenDFCompat(const FSSpec *spec,
  251.                                 char permission,
  252.                                 short *refNum)
  253. {
  254. #if !__MACOSSEVENORLATER
  255.     if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
  256.     {
  257.         OSErr            result;
  258.         HParamBlockRec    pb;
  259.         
  260.         pb.ioParam.ioVRefNum = spec->vRefNum;
  261.         pb.fileParam.ioDirID = spec->parID;
  262.         pb.ioParam.ioNamePtr = (StringPtr) &(spec->name);
  263.         pb.ioParam.ioVersNum = 0;
  264.         pb.ioParam.ioPermssn = permission;
  265.         pb.ioParam.ioMisc = NULL;
  266.         result = PBHOpenSync(&pb);    /* OpenDF not supported by System 6, so use Open */
  267.         *refNum = pb.ioParam.ioRefNum;
  268.         return ( result );
  269.     }
  270.     else
  271. #endif    /* !__MACOSSEVENORLATER */
  272.     {
  273.         return ( FSpOpenDF(spec, permission, refNum) );
  274.     }
  275. }
  276.  
  277. /*****************************************************************************/
  278.  
  279. pascal    OSErr    FSpOpenRFCompat(const FSSpec *spec,
  280.                                 char permission,
  281.                                 short *refNum)
  282. {
  283. #if !__MACOSSEVENORLATER
  284.     if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
  285.     {
  286.         OSErr            result;
  287.         HParamBlockRec    pb;
  288.         
  289.         pb.ioParam.ioVRefNum = spec->vRefNum;
  290.         pb.fileParam.ioDirID = spec->parID;
  291.         pb.ioParam.ioNamePtr = (StringPtr) &(spec->name);
  292.         pb.ioParam.ioVersNum = 0;
  293.         pb.ioParam.ioPermssn = permission;
  294.         pb.ioParam.ioMisc = NULL;
  295.         result = PBHOpenRFSync(&pb);
  296.         *refNum = pb.ioParam.ioRefNum;
  297.         return ( result );
  298.     }
  299.     else
  300. #endif    /* !__MACOSSEVENORLATER */
  301.     {
  302.         return ( FSpOpenRF(spec, permission, refNum) );
  303.     }
  304. }
  305.  
  306. /*****************************************************************************/
  307.  
  308. pascal    OSErr    FSpCreateCompat(const FSSpec *spec,
  309.                                 OSType creator,
  310.                                 OSType fileType,
  311.                                 ScriptCode scriptTag)
  312. {
  313. #if !__MACOSSEVENFIVEONEORLATER
  314.     OSErr            result;
  315.     UniversalFMPB    pb;
  316.  
  317.     
  318.     if (
  319. #if !__MACOSSEVENORLATER
  320.          (!FSHasFSSpecCalls() && !QTHasFSSpecCalls()) ||
  321. #endif    /* !__MACOSSEVENORLATER */
  322.          !HasFSpCreateScriptSupportFix() )
  323.     {
  324.         /*    If FSpCreate isn't called, this code will be executed */
  325.         pb.hPB.fileParam.ioVRefNum = spec->vRefNum;
  326.         pb.hPB.fileParam.ioDirID = spec->parID;
  327.         pb.hPB.fileParam.ioNamePtr = (StringPtr) &(spec->name);
  328.         pb.hPB.fileParam.ioFVersNum = 0;
  329.         result = PBHCreateSync(&(pb.hPB));
  330.         if ( result == noErr )
  331.         {
  332.             /* get info on created item */
  333.             pb.ciPB.hFileInfo.ioFDirIndex = 0;
  334.             result = PBGetCatInfoSync(&(pb.ciPB));
  335.             if ( result == noErr )
  336.             {
  337.                 /* Set fdScript in FXInfo */
  338.                 /* The negative script constants (smSystemScript, smCurrentScript, and smAllScripts) */
  339.                 /* don't make sense on disk, so only use scriptTag if scriptTag >= smRoman */
  340.                 /* (smRoman is 0). fdScript is valid if high bit is set (see IM-6, page 9-38) */
  341.                 pb.ciPB.hFileInfo.ioFlXFndrInfo.fdScript = (scriptTag >= smRoman) ?
  342.                                                             ((char)scriptTag | (char)0x80) :
  343.                                                             (smRoman);
  344.                 /* Set creator/fileType */
  345.                 pb.ciPB.hFileInfo.ioFlFndrInfo.fdCreator = creator;
  346.                 pb.ciPB.hFileInfo.ioFlFndrInfo.fdType = fileType;
  347.                 /* Restore ioDirID field in pb which was changed by PBGetCatInfo */
  348.                 pb.ciPB.hFileInfo.ioDirID = spec->parID;
  349.                 result = PBSetCatInfoSync(&(pb.ciPB));
  350.             }
  351.         }
  352.         return ( result );
  353.     }
  354.     else
  355. #endif    /* !__MACOSSEVENFIVEONEORLATER */
  356.     {
  357.         return ( FSpCreate(spec, creator, fileType, scriptTag) );
  358.     }
  359. }
  360.  
  361. /*****************************************************************************/
  362.  
  363. pascal    OSErr    FSpDirCreateCompat(const FSSpec *spec,
  364.                                    ScriptCode scriptTag,
  365.                                    long *createdDirID)
  366. {
  367. #if !__MACOSSEVENORLATER
  368.     if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
  369.     {
  370.         OSErr            result;
  371.         UniversalFMPB    pb;
  372.         
  373.         pb.hPB.fileParam.ioVRefNum = spec->vRefNum;
  374.         pb.hPB.fileParam.ioDirID = spec->parID;
  375.         pb.hPB.fileParam.ioNamePtr = (StringPtr) &(spec->name);
  376.         result = PBDirCreateSync(&(pb.hPB));
  377.         *createdDirID = pb.hPB.fileParam.ioDirID;
  378.         if ( result == noErr )
  379.         {
  380.             /* get info on created item */
  381.             pb.ciPB.dirInfo.ioFDirIndex = 0;
  382.             pb.ciPB.dirInfo.ioDrDirID = spec->parID;
  383.             result = PBGetCatInfoSync(&(pb.ciPB));
  384.             if ( result == noErr )
  385.             {
  386.                 /* Set frScript in DXInfo */
  387.                 /* The negative script constants (smSystemScript, smCurrentScript, and smAllScripts) */
  388.                 /* don't make sense on disk, so only use scriptTag if scriptTag >= smRoman */
  389.                 /* (smRoman is 0). frScript is valid if high bit is set (see IM-6, page 9-38) */
  390.                 pb.ciPB.dirInfo.ioDrFndrInfo.frScript = (scriptTag >= smRoman) ?
  391.                                                             ((char)scriptTag | (char)0x80) :
  392.                                                             (smRoman);
  393.                 /* Restore ioDirID field in pb which was changed by PBGetCatInfo */
  394.                 pb.ciPB.dirInfo.ioDrDirID = spec->parID;            
  395.                 result = PBSetCatInfoSync(&(pb.ciPB));
  396.             }
  397.         }
  398.         return ( result );
  399.     }
  400.     else
  401. #endif    /* !__MACOSSEVENORLATER */
  402.     {
  403.         return ( FSpDirCreate(spec, scriptTag, createdDirID) );
  404.     }
  405. }
  406.  
  407. /*****************************************************************************/
  408.  
  409. pascal    OSErr    FSpDeleteCompat(const FSSpec *spec)
  410. {
  411. #if !__MACOSSEVENORLATER
  412.     if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
  413.     {
  414.         HParamBlockRec    pb;
  415.         
  416.         pb.ioParam.ioVRefNum = spec->vRefNum;
  417.         pb.fileParam.ioDirID = spec->parID;
  418.         pb.ioParam.ioNamePtr = (StringPtr) &(spec->name);
  419.         pb.ioParam.ioVersNum = 0;
  420.         return ( PBHDeleteSync(&pb) );
  421.     }
  422.     else
  423. #endif    /* !__MACOSSEVENORLATER */
  424.     {
  425.         return ( FSpDelete(spec) );
  426.     }
  427. }
  428.  
  429. /*****************************************************************************/
  430.  
  431. pascal    OSErr    FSpGetFInfoCompat(const FSSpec *spec,
  432.                                   FInfo *fndrInfo)
  433. {
  434. #if !__MACOSSEVENORLATER
  435.     if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
  436.     {
  437.         OSErr            result;
  438.         HParamBlockRec    pb;
  439.         
  440.         pb.fileParam.ioVRefNum = spec->vRefNum;
  441.         pb.fileParam.ioDirID = spec->parID;
  442.         pb.fileParam.ioNamePtr = (StringPtr) &(spec->name);
  443.         pb.fileParam.ioFVersNum = 0;
  444.         pb.fileParam.ioFDirIndex = 0;
  445.         result = PBHGetFInfoSync(&pb);
  446.         *fndrInfo = pb.fileParam.ioFlFndrInfo;
  447.         return ( result );
  448.     }
  449.     else
  450. #endif    /* !__MACOSSEVENORLATER */
  451.     {
  452.         return ( FSpGetFInfo(spec, fndrInfo) );
  453.     }
  454. }
  455.  
  456. /*****************************************************************************/
  457.  
  458. pascal    OSErr    FSpSetFInfoCompat(const FSSpec *spec,
  459.                                   const FInfo *fndrInfo)
  460. {
  461. #if !__MACOSSEVENORLATER
  462.     if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
  463.     {
  464.         OSErr            result;
  465.         HParamBlockRec    pb;
  466.         
  467.         pb.fileParam.ioVRefNum = spec->vRefNum;
  468.         pb.fileParam.ioDirID = spec->parID;
  469.         pb.fileParam.ioNamePtr = (StringPtr) &(spec->name);
  470.         pb.fileParam.ioFVersNum = 0;
  471.         pb.fileParam.ioFDirIndex = 0;
  472.         result = PBHGetFInfoSync(&pb);
  473.         if ( result == noErr )
  474.         {
  475.             pb.fileParam.ioFlFndrInfo = *fndrInfo;
  476.             pb.fileParam.ioDirID = spec->parID;
  477.             result = PBHSetFInfoSync(&pb);
  478.         }
  479.         return ( result );
  480.     }
  481.     else
  482. #endif    /* !__MACOSSEVENORLATER */
  483.     {
  484.         return ( FSpSetFInfo(spec, fndrInfo) );
  485.     }
  486. }
  487.  
  488. /*****************************************************************************/
  489.  
  490. pascal    OSErr    FSpSetFLockCompat(const FSSpec *spec)
  491. {
  492. #if !__MACOSSEVENORLATER
  493.     if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
  494.     {
  495.         HParamBlockRec    pb;
  496.         
  497.         pb.fileParam.ioVRefNum = spec->vRefNum;
  498.         pb.fileParam.ioDirID = spec->parID;
  499.         pb.fileParam.ioNamePtr = (StringPtr) &(spec->name);
  500.         pb.fileParam.ioFVersNum = 0;
  501.         return ( PBHSetFLockSync(&pb) );
  502.     }
  503.     else
  504. #endif    /* !__MACOSSEVENORLATER */
  505.     {
  506.         return ( FSpSetFLock(spec) );
  507.     }
  508. }
  509.  
  510. /*****************************************************************************/
  511.  
  512. pascal    OSErr    FSpRstFLockCompat(const FSSpec *spec)
  513. {
  514. #if !__MACOSSEVENORLATER
  515.     if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
  516.     {
  517.         HParamBlockRec    pb;
  518.         
  519.         pb.fileParam.ioVRefNum = spec->vRefNum;
  520.         pb.fileParam.ioDirID = spec->parID;
  521.         pb.fileParam.ioNamePtr = (StringPtr) &(spec->name);
  522.         pb.fileParam.ioFVersNum = 0;
  523.         return ( PBHRstFLockSync(&pb) );
  524.     }
  525.     else
  526. #endif    /* !__MACOSSEVENORLATER */
  527.     {
  528.         return ( FSpRstFLock(spec) );
  529.     }
  530. }
  531.  
  532. /*****************************************************************************/
  533.  
  534. pascal    OSErr    FSpRenameCompat(const FSSpec *spec,
  535.                                 ConstStr255Param newName)
  536. {
  537. #if !__MACOSSEVENORLATER
  538.     if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
  539.     {
  540.         HParamBlockRec    pb;
  541.         
  542.         pb.ioParam.ioVRefNum = spec->vRefNum;
  543.         pb.fileParam.ioDirID = spec->parID;
  544.         pb.ioParam.ioNamePtr = (StringPtr) &(spec->name);
  545.         pb.ioParam.ioVersNum = 0;
  546.         pb.ioParam.ioMisc = (Ptr) newName;
  547.         return ( PBHRenameSync(&pb) );
  548.     }
  549.     else
  550. #endif    /* !__MACOSSEVENORLATER */
  551.     {
  552.         return ( FSpRename(spec, newName) );
  553.     }
  554. }
  555.  
  556. /*****************************************************************************/
  557.  
  558. pascal    OSErr    FSpCatMoveCompat(const FSSpec *source,
  559.                                  const FSSpec *dest)
  560. {
  561. #if !__MACOSSEVENORLATER
  562.     if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
  563.     {
  564.         CMovePBRec    pb;
  565.         
  566.         /* source and destination volume must be the same */
  567.         if ( source->vRefNum != dest->vRefNum )
  568.             return ( paramErr );
  569.         
  570.         pb.ioNamePtr = (StringPtr) &(source->name);
  571.         pb.ioVRefNum = source->vRefNum;
  572.         pb.ioDirID = source->parID;
  573.         pb.ioNewDirID = dest->parID;
  574.         pb.ioNewName = (StringPtr) &(dest->name);
  575.         return ( PBCatMoveSync(&pb) );
  576.     }
  577.     else
  578. #endif    /* !__MACOSSEVENORLATER */
  579.     {
  580.         return ( FSpCatMove(source, dest) );
  581.     }
  582. }
  583.  
  584. /*****************************************************************************/
  585.  
  586. /* GenerateUniqueName generates a name that is unique in both dir1 and dir2 */
  587. /* on the specified volume. Ripped off from Feldman's code. */
  588.  
  589. #if !__MACOSSEVENFIVEORLATER
  590. static    OSErr    GenerateUniqueName(short volume,
  591.                                    long *startSeed,
  592.                                    long dir1,
  593.                                    long dir2,
  594.                                    StringPtr uniqueName)
  595. {
  596.     OSErr            error = noErr;
  597.     long            i;
  598.     CInfoPBRec        cinfo;
  599.     unsigned char    hexStr[16];
  600.     
  601.     for ( i = 0; i < 16; ++i )
  602.     {
  603.         if ( i < 10 )
  604.         {
  605.             hexStr[i] = 0x30 + i;
  606.         }
  607.         else
  608.         {
  609.             hexStr[i] = 0x37 + i;
  610.         }
  611.     }
  612.     
  613.     cinfo.hFileInfo.ioVRefNum = volume;
  614.     cinfo.hFileInfo.ioFDirIndex = 0;
  615.     cinfo.hFileInfo.ioNamePtr = uniqueName;
  616.  
  617.     while ( error != fnfErr )
  618.     {
  619.         (*startSeed)++;        
  620.         cinfo.hFileInfo.ioNamePtr[0] = 8;
  621.         for ( i = 1; i <= 8; i++ )
  622.         {
  623.             cinfo.hFileInfo.ioNamePtr[i] = hexStr[((*startSeed >> ((8-i)*4)) & 0xf)];
  624.         }
  625.         cinfo.hFileInfo.ioDirID = dir1;
  626.         error = fnfErr;
  627.         for ( i = 1; i <= 2; i++ )
  628.         {
  629.             error = error & PBGetCatInfoSync(&cinfo);
  630.             cinfo.hFileInfo.ioDirID = dir2;
  631.             if ( (error != fnfErr) && (error != noErr) )
  632.             {
  633.                 return ( error );
  634.             }
  635.         }
  636.     }
  637.     return ( noErr );
  638. }
  639. #endif    /* !__MACOSSEVENFIVEORLATER */
  640.  
  641. /*****************************************************************************/
  642.  
  643. pascal    OSErr    FSpExchangeFilesCompat(const FSSpec *source,
  644.                                        const FSSpec *dest)
  645. {
  646. #if !__MACOSSEVENFIVEORLATER
  647.     if ( 
  648. #if !__MACOSSEVENORLATER
  649.          !FSHasFSSpecCalls() ||
  650. #endif    /* !__MACOSSEVENORLATER */
  651.          !HasFSpExchangeFilesCompatibilityFix() )
  652.     {
  653.         HParamBlockRec            pb;
  654.         CInfoPBRec                catInfoSource, catInfoDest;
  655.         OSErr                    result, result2;
  656.         Str31                    unique1, unique2;
  657.         StringPtr                unique1Ptr, unique2Ptr, swapola;
  658.         GetVolParmsInfoBuffer    volInfo;
  659.         long                    theSeed, temp;
  660.         
  661.         /* Make sure the source and destination are on the same volume */
  662.         if ( source->vRefNum != dest->vRefNum )
  663.         {
  664.             result = diffVolErr;
  665.             goto errorExit3;
  666.         }
  667.         
  668.         /* Try PBExchangeFiles first since it preserves the file ID reference */
  669.         pb.fidParam.ioNamePtr = (StringPtr) &(source->name);
  670.         pb.fidParam.ioVRefNum = source->vRefNum;
  671.         pb.fidParam.ioDestNamePtr = (StringPtr) &(dest->name);
  672.         pb.fidParam.ioDestDirID = dest->parID;
  673.         pb.fidParam.ioSrcDirID = source->parID;
  674.     
  675.         result = PBExchangeFilesSync(&pb);
  676.     
  677.         /* Note: The compatibility case won't work for files with *Btree control blocks. */
  678.         /* Right now the only *Btree files are created by the system. */
  679.         if ( result != noErr )
  680.         {
  681.             pb.ioParam.ioNamePtr = NULL;
  682.             pb.ioParam.ioBuffer = (Ptr) &volInfo;
  683.             pb.ioParam.ioReqCount = sizeof(volInfo);
  684.             result2 = PBHGetVolParmsSync(&pb);
  685.             
  686.             /* continue if volume has no fileID support (or no GetVolParms support) */
  687.             if ( (result2 == noErr) && hasFileIDs(volInfo) )
  688.             {
  689.                 goto errorExit3;
  690.             }
  691.     
  692.             /* Get the catalog information for each file */
  693.             /* and make sure both files are *really* files */
  694.             catInfoSource.hFileInfo.ioVRefNum = source->vRefNum;
  695.             catInfoSource.hFileInfo.ioFDirIndex = 0;
  696.             catInfoSource.hFileInfo.ioNamePtr = (StringPtr) &(source->name);
  697.             catInfoSource.hFileInfo.ioDirID = source->parID;
  698.             catInfoSource.hFileInfo.ioACUser = 0; /* ioACUser used to be filler2 */
  699.             result = PBGetCatInfoSync(&catInfoSource);
  700.             if ( result != noErr )
  701.             {
  702.                 goto errorExit3;
  703.             }
  704.             if ( (catInfoSource.hFileInfo.ioFlAttrib & ioDirMask) != 0 )
  705.             {
  706.                 result = notAFileErr;
  707.                 goto errorExit3;
  708.             }
  709.             
  710.             catInfoDest.hFileInfo.ioVRefNum = dest->vRefNum;
  711.             catInfoDest.hFileInfo.ioFDirIndex = 0;
  712.             catInfoDest.hFileInfo.ioNamePtr = (StringPtr) &(dest->name);
  713.             catInfoDest.hFileInfo.ioDirID = dest->parID;
  714.             catInfoDest.hFileInfo.ioACUser = 0; /* ioACUser used to be filler2 */
  715.             result = PBGetCatInfoSync(&catInfoDest);
  716.             if ( result != noErr )
  717.             {
  718.                 goto errorExit3;
  719.             }
  720.             if ( (catInfoDest.hFileInfo.ioFlAttrib & ioDirMask) != 0 )
  721.             {
  722.                 result = notAFileErr;
  723.                 goto errorExit3;
  724.             }
  725.             
  726.             /* generate 2 filenames that are unique in both directories */
  727.             theSeed = 0x64666A6C;    /* a fine unlikely filename */
  728.             unique1Ptr = (StringPtr)&unique1;
  729.             unique2Ptr = (StringPtr)&unique2;
  730.             
  731.             result = GenerateUniqueName(source->vRefNum, &theSeed, source->parID, dest->parID, unique1Ptr);
  732.             if ( result != noErr )
  733.             {
  734.                 goto errorExit3;
  735.             }
  736.     
  737.             GenerateUniqueName(source->vRefNum, &theSeed, source->parID, dest->parID, unique2Ptr);
  738.             if ( result != noErr )
  739.             {
  740.                 goto errorExit3;
  741.             }
  742.     
  743.             /* rename source to unique1 */
  744.             pb.fileParam.ioNamePtr = (StringPtr) &(source->name);
  745.             pb.ioParam.ioMisc = (Ptr) unique1Ptr;
  746.             pb.ioParam.ioVersNum = 0;
  747.             result = PBHRenameSync(&pb);
  748.             if ( result != noErr )
  749.             {
  750.                 goto errorExit3;
  751.             }
  752.             
  753.             /* rename dest to unique2 */
  754.             pb.ioParam.ioMisc = (Ptr) unique2Ptr;
  755.             pb.ioParam.ioVersNum = 0;
  756.             pb.fileParam.ioNamePtr = (StringPtr) &(dest->name);
  757.             pb.fileParam.ioDirID = dest->parID;
  758.             result = PBHRenameSync(&pb);
  759.             if ( result != noErr )
  760.             {
  761.                 goto errorExit2;    /* back out gracefully by renaming unique1 back to source */
  762.             }
  763.                 
  764.             /* If files are not in same directory, swap their locations */
  765.             if ( source->parID != dest->parID )
  766.             {
  767.                 /* move source file to dest directory */
  768.                 pb.copyParam.ioNamePtr = unique1Ptr;
  769.                 pb.copyParam.ioNewName = NULL;
  770.                 pb.copyParam.ioNewDirID = dest->parID;
  771.                 pb.copyParam.ioDirID = source->parID;
  772.                 result = PBCatMoveSync((CMovePBPtr) &pb);
  773.                 if ( result != noErr )
  774.                 {
  775.                     goto errorExit1;    /* back out gracefully by renaming both files to original names */
  776.                 }
  777.                 
  778.                 /* move dest file to source directory */
  779.                 pb.copyParam.ioNamePtr = unique2Ptr;
  780.                 pb.copyParam.ioNewDirID = source->parID;
  781.                 pb.copyParam.ioDirID = dest->parID;
  782.                 result = PBCatMoveSync((CMovePBPtr) &pb);
  783.                 if ( result != noErr)
  784.                 {
  785.                     /* life is very bad.  We'll at least try to move source back */
  786.                     pb.copyParam.ioNamePtr = unique1Ptr;
  787.                     pb.copyParam.ioNewName = NULL;
  788.                     pb.copyParam.ioNewDirID = source->parID;
  789.                     pb.copyParam.ioDirID = dest->parID;
  790.                     (void) PBCatMoveSync((CMovePBPtr) &pb);    /* ignore errors */
  791.                     goto errorExit1;    /* back out gracefully by renaming both files to original names */
  792.                 }
  793.             }
  794.             
  795.             /* Make unique1Ptr point to file in source->parID */
  796.             /* and unique2Ptr point to file in dest->parID */
  797.             /* This lets us fall through to the rename code below */
  798.             swapola = unique1Ptr;
  799.             unique1Ptr = unique2Ptr;
  800.             unique2Ptr = swapola;
  801.     
  802.             /* At this point, the files are in their new locations (if they were moved) */
  803.             /* Source is named Unique1 (name pointed to by unique2Ptr) and is in dest->parID */
  804.             /* Dest is named Unique2 (name pointed to by unique1Ptr) and is in source->parID */
  805.             /* Need to swap attributes except mod date and swap names */
  806.     
  807.             /* swap the catalog info by re-aiming the CInfoPB's */
  808.             catInfoSource.hFileInfo.ioNamePtr = unique1Ptr;
  809.             catInfoDest.hFileInfo.ioNamePtr = unique2Ptr;
  810.             
  811.             catInfoSource.hFileInfo.ioDirID = source->parID;
  812.             catInfoDest.hFileInfo.ioDirID = dest->parID;
  813.             
  814.             /* Swap the original mod dates with each file */
  815.             temp = catInfoSource.hFileInfo.ioFlMdDat;
  816.             catInfoSource.hFileInfo.ioFlMdDat = catInfoDest.hFileInfo.ioFlMdDat;
  817.             catInfoDest.hFileInfo.ioFlMdDat = temp;
  818.             
  819.             /* Here's the swap (ignore errors) */
  820.             (void) PBSetCatInfoSync(&catInfoSource); 
  821.             (void) PBSetCatInfoSync(&catInfoDest);
  822.             
  823.             /* rename unique2 back to dest */
  824. errorExit1:
  825.             pb.ioParam.ioMisc = (Ptr) &(dest->name);
  826.             pb.ioParam.ioVersNum = 0;
  827.             pb.fileParam.ioNamePtr = unique2Ptr;
  828.             pb.fileParam.ioDirID = dest->parID;
  829.             (void) PBHRenameSync(&pb);    /* ignore errors */
  830.     
  831.             /* rename unique1 back to source */
  832. errorExit2:
  833.             pb.ioParam.ioMisc = (Ptr) &(source->name);
  834.             pb.ioParam.ioVersNum = 0;
  835.             pb.fileParam.ioNamePtr = unique1Ptr;
  836.             pb.fileParam.ioDirID = source->parID;
  837.             (void) PBHRenameSync(&pb); /* ignore errors */
  838.         }
  839. errorExit3: { /* null statement */ }
  840.         return ( result );
  841.     }
  842.     else
  843. #endif    /* !__MACOSSEVENFIVEORLATER */
  844.     {
  845.         return ( FSpExchangeFiles(source, dest) );
  846.     }
  847. }
  848.  
  849. /*****************************************************************************/
  850.  
  851. /* 
  852. **    Resource Manager FSp calls
  853. */
  854.  
  855. /*****************************************************************************/
  856.  
  857. pascal    short    FSpOpenResFileCompat(const FSSpec *spec,
  858.                                      SignedByte permission)
  859. {
  860. #if !__MACOSSEVENORLATER
  861.     if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
  862.     {
  863.         return ( HOpenResFile(spec->vRefNum, spec->parID, spec->name, permission) );
  864.     }
  865.     else
  866. #endif    /* !__MACOSSEVENORLATER */
  867.     {
  868.         return ( FSpOpenResFile(spec, permission) );
  869.     }
  870. }
  871.  
  872. /*****************************************************************************/
  873.  
  874. pascal    void    FSpCreateResFileCompat(const FSSpec *spec,
  875.                                        OSType creator,
  876.                                        OSType fileType,
  877.                                        ScriptCode scriptTag)
  878. {    
  879. #if !__MACOSSEVENFIVEONEORLATER
  880.     if (
  881. #if !__MACOSSEVENORLATER
  882.          (!FSHasFSSpecCalls() && !QTHasFSSpecCalls()) ||
  883. #endif    /* !__MACOSSEVENORLATER */
  884.          !HasFSpCreateScriptSupportFix() )
  885.     {
  886.         OSErr            result;
  887.         CInfoPBRec        pb;
  888.         
  889.         HCreateResFile(spec->vRefNum, spec->parID, spec->name);
  890.         if ( ResError() == noErr )
  891.         {
  892.             /* get info on created item */
  893.             pb.hFileInfo.ioVRefNum = spec->vRefNum;
  894.             pb.hFileInfo.ioDirID = spec->parID;
  895.             pb.hFileInfo.ioNamePtr = (StringPtr) &(spec->name);
  896.             pb.hFileInfo.ioFDirIndex = 0;
  897.             result = PBGetCatInfoSync(&pb);
  898.             if ( result == noErr )
  899.             {
  900.                 /* Set fdScript in FXInfo */
  901.                 /* The negative script constants (smSystemScript, smCurrentScript, and smAllScripts) */
  902.                 /* don't make sense on disk, so only use scriptTag if scriptTag >= smRoman */
  903.                 /* (smRoman is 0). fdScript is valid if high bit is set (see IM-6, page 9-38) */
  904.                 pb.hFileInfo.ioFlXFndrInfo.fdScript = (scriptTag >= smRoman) ?
  905.                                                         ((char)scriptTag | (char)0x80) :
  906.                                                         (smRoman);
  907.                 /* Set creator/fileType */
  908.                 pb.hFileInfo.ioFlFndrInfo.fdCreator = creator;
  909.                 pb.hFileInfo.ioFlFndrInfo.fdType = fileType;
  910.                 
  911.                 /* Restore ioDirID field in pb which was changed by PBGetCatInfo */
  912.                 pb.hFileInfo.ioDirID = spec->parID;
  913.                 result = PBSetCatInfoSync(&pb);
  914.             }
  915.             /* Set ResErr low memory global to result */
  916.             LMSetResErr(result);
  917.         }
  918.         return;
  919.     }
  920.     else
  921. #endif    /* !__MACOSSEVENFIVEONEORLATER */
  922.     {
  923.         FSpCreateResFile(spec, creator, fileType, scriptTag);
  924.         return;
  925.     }
  926. }
  927.  
  928. /*****************************************************************************/
  929.